package com.keqing.tomato.fragment;


import static android.content.Context.MODE_PRIVATE;
import static android.widget.Toast.LENGTH_SHORT;
import static com.keqing.tomato.R.drawable.ic_baseline_hourglass_top_24;
import static com.keqing.tomato.R.string.reset_toast;
import static com.keqing.tomato.bean.MySetting.default_focus_sound;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Vibrator;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.keqing.tomato.LandscapeActivity;
import com.keqing.tomato.R;
import com.keqing.tomato.bean.MySetting;
import com.keqing.tomato.database.TomatoHistory;
import com.keqing.tomato.service.TimerService;
import com.keqing.tomato.util.TimeUtil;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;


public class FragmentTomatoTime extends Fragment implements View.OnClickListener {
    private static final int begin_focus = 1;
    private static final int focusing = 2;
    private static final int begin_rest = 3;
    private static final int resting = 4;
    //当前状态
    private static int timeBtnState = begin_focus;
    private static boolean countDown = true;
    private Button timeBtn;
    private TextView resetBtn;
    private TextView timeModeBtn;
    private TextView tvEndTime;
    private Activity activity;
    private TextView landscapeBtn;
    private TextView tvTime;
    private BroadcastReceiver broadcastReceiver;
    private TimerService timerService;
    private final ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("tomato", "ServiceConnection - onServiceConnected()");
            TimerService.TimerServiceBinder binder = (TimerService.TimerServiceBinder) service;
            timerService = binder.getTimerService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("tomato", "ServiceConnection - onServiceDisconnected()");

        }
    };
    private int focusTime;
    private int restTime;
    private String focusSound;
    private String restSound;
    private boolean vibration;
    private boolean autoRest;
    Handler handler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == begin_rest) {
                if (autoRest) {
                    new Handler(Looper.myLooper()) {
                        @Override
                        public void handleMessage(@NonNull Message msg) {
                            super.handleMessage(msg);
                            handleTimeTask();
                        }
                    }.postDelayed(null, 1000);
                }
            }
            if (msg.what == begin_focus) {

            }
        }
    };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.e("tomato", "FragmentTomatoTime - onCreateView");
        return inflater.inflate(R.layout.fragment_tomato_time, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.e("tomato", "FragmentTomatoTime - onViewCreated");
        activity = getActivity();
        timeBtn = view.findViewById(R.id.time_btn);
        resetBtn = view.findViewById(R.id.btn_reset);
        tvTime = view.findViewById(R.id.tv_time);
        landscapeBtn = view.findViewById(R.id.btn_landscape);
        timeModeBtn = view.findViewById(R.id.btn_time_mode);
        tvEndTime = view.findViewById(R.id.tv_end_time);

        timeBtn.setOnClickListener(this);
        resetBtn.setOnClickListener(this);
        timeModeBtn.setOnClickListener(this);
        landscapeBtn.setOnClickListener(this);

        Intent intent = new Intent(activity.getApplicationContext(), TimerService.class);
        activity.bindService(intent, conn, Context.BIND_AUTO_CREATE);
        registerBroadcastReceivers();

        initSettings();

        tvTime.setText(TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
    }

    private void initSettings() {
        SharedPreferences preferences = activity.getSharedPreferences("mysettings", MODE_PRIVATE);
        focusTime = preferences.getInt("focusTime", MySetting.default_focus_time);
        restTime = preferences.getInt("restTime", MySetting.default_rest_time);
        focusSound = preferences.getString("focusSound", default_focus_sound);
        restSound = preferences.getString("restSound", MySetting.default_rest_sound);
        vibration = preferences.getBoolean("vibration", MySetting.default_vibration);
        autoRest = preferences.getBoolean("autoRest", MySetting.default_auto_rest);
    }

    private void registerBroadcastReceivers() {
        this.broadcastReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                Bundle bundle = intent.getExtras();
                String minSec = bundle.getString("minSec");
                tvTime.setText(minSec);
                int what = bundle.getInt("what");
                if (what == TimerService.time_ticking) {
                }
                if (what == TimerService.time_finished) {
                    handleTimeTask();
                }
            }
        };
        activity.registerReceiver(this.broadcastReceiver, new IntentFilter("timer"));
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.time_btn) {
            handleTimeTask();
        } else if (v.getId() == R.id.btn_landscape) {
            landscapeBtnOnClick();
        } else if (v.getId() == R.id.btn_reset) {
            if (timeBtnState == begin_rest) {
                Toast.makeText(activity, "重置成功", LENGTH_SHORT).show();
                timeBtnState = begin_focus;
                timeBtn.setText(R.string.time_begin_focus);
                timeBtn.setEnabled(true);
                tvTime.setText(TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
            } else if (timeBtnState == focusing || timeBtnState == resting) {
                Toast.makeText(activity, reset_toast, LENGTH_SHORT).show();
            } else {
                Toast.makeText(activity, "重置成功", LENGTH_SHORT).show();
            }
        } else if (v.getId() == R.id.btn_time_mode) {
            if (timeBtnState == focusing || timeBtnState == resting) {
                Toast.makeText(activity, "请在计时结束后设置", LENGTH_SHORT).show();
            } else if (timeBtnState == begin_rest || timeBtnState == begin_focus) {
                countDown = !countDown;
                if (countDown) {
                    timeModeBtn.setText("正计时");
                    @SuppressLint("UseCompatLoadingForDrawables")
                    Drawable drawable = activity.getResources().getDrawable(R.drawable.ic_baseline_hourglass_empty_24);
                    drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
                    timeModeBtn.setCompoundDrawables(null, drawable, null, null);
                    if (timeBtnState == begin_rest) {
                        tvTime.setText(TimerService.msToMinSec(restTime * TimerService.millisInOneMinute));
                        tvEndTime.setVisibility(View.INVISIBLE);
                    } else {
                        tvTime.setText(TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
                        tvEndTime.setVisibility(View.INVISIBLE);
                    }
                } else {
                    timeModeBtn.setText("倒计时");
                    @SuppressLint("UseCompatLoadingForDrawables")
                    Drawable drawable = activity.getResources().getDrawable(ic_baseline_hourglass_top_24);
                    drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
                    timeModeBtn.setCompoundDrawables(null, drawable, null, null);
                    tvTime.setText(TimerService.msToMinSec(0));
                    if (timeBtnState == begin_rest) {
                        tvEndTime.setText(TimerService.msToMinSec(restTime * TimerService.millisInOneMinute));
                        tvEndTime.setVisibility(View.VISIBLE);
                    } else {
                        tvEndTime.setText(TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
                        tvEndTime.setVisibility(View.VISIBLE);
                    }
                }
            }
        }
    }

    private void landscapeBtnOnClick() {
        Intent intent = new Intent(activity, LandscapeActivity.class);
        Bundle bundle = new Bundle();
        if (timeBtnState == begin_focus) {
            bundle.putString("time", TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
        } else if (timeBtnState == begin_rest) {
            bundle.putString("time", TimerService.msToMinSec(restTime * TimerService.millisInOneMinute));
        }
        intent.putExtras(bundle);
        startActivityForResult(intent, 100);
    }

    // 专注按钮
    private void handleTimeTask() {
        if (timeBtnState == begin_focus) {
            timeBtn.setText("专注中...");
            timeBtn.setEnabled(false);
            timerService.addTimer(focusTime * TimerService.millisInOneMinute, countDown);
            timeBtnState = focusing;
        } else if (timeBtnState == begin_rest) {
            timeBtn.setText("休息中...");
            timeBtn.setEnabled(false);
            timerService.addTimer(restTime * TimerService.millisInOneMinute, countDown);
            timeBtnState = resting;
        } else if (timeBtnState == focusing) {
            timeBtnState = begin_rest;
            //保存数据库
            TomatoHistory history = new TomatoHistory(
                    "未名番茄钟",
                    focusTime,
                    TimeUtil.getDateByOffset(new Date(), Calendar.MINUTE, -focusTime),
                    new Date());
            history.save();
            //响铃
            palySound(focusSound);
            //振动
            palyVibration();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    timeBtn.setText("开始\n休息");
                    timeBtn.setEnabled(true);
                    if (countDown) {
                        tvTime.setText(TimerService.msToMinSec(restTime * TimerService.millisInOneMinute));
                    } else {
                        tvTime.setText(TimerService.msToMinSec(0));
                        tvEndTime.setText(TimerService.msToMinSec(restTime * TimerService.millisInOneMinute));
                        tvEndTime.setVisibility(View.VISIBLE);
                    }
                    Message message = new Message();
                    message.what = begin_rest;
                    handler.sendMessage(message);
                }
            }, 1000);
        } else if (timeBtnState == resting) {
            timeBtnState = begin_focus;
            //响铃
            palySound(restSound);
            //振动
            palyVibration();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    timeBtn.setText("开始\n专注");
                    timeBtn.setEnabled(true);
                    if (countDown) {
                        tvTime.setText(TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
                    } else {
                        tvTime.setText(TimerService.msToMinSec(0));
                        tvEndTime.setText(TimerService.msToMinSec(focusTime * TimerService.millisInOneMinute));
                        tvEndTime.setVisibility(View.VISIBLE);
                    }
                    Message message = new Message();
                    message.what = begin_focus;
                    handler.sendMessage(message);
                }
            }, 1000);
        }
    }

    @SuppressLint("WrongConstant")
    private void palyVibration() {
        if (vibration) {
            Vibrator vibrator = (Vibrator) this.getContext().getSystemService("vibrator");
            vibrator.vibrate(new long[]{50, 500, 100, 500, 50, 500, 100, 500}, -1);
        }
    }

    private void palySound(String soundFile) {
        SoundPool soundPool;
        //实例化SoundPool
        //sdk版本21是SoundPool 的一个分水岭
        if (Build.VERSION.SDK_INT >= 21) {
            SoundPool.Builder builder = new SoundPool.Builder();
            //传入最多播放音频数量,
            builder.setMaxStreams(1);
            //AudioAttributes是一个封装音频各种属性的方法
            AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
            //设置音频流的合适的属性
            attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
            //加载一个AudioAttributes
            builder.setAudioAttributes(attrBuilder.build());
            soundPool = builder.build();
        } else {
            /**
             * 第一个参数：int maxStreams：SoundPool对象的最大并发流数
             * 第二个参数：int streamType：AudioManager中描述的音频流类型
             *第三个参数：int srcQuality：采样率转换器的质量。 目前没有效果。 使用0作为默认值。
             */
            soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
        }

        //可以通过四种途径来记载一个音频资源：
        //1.通过一个AssetFileDescriptor对象
        //int load(AssetFileDescriptor afd, int priority)
        //2.通过一个资源ID
        //int load(Context context, int resId, int priority)
        //3.通过指定的路径加载
        //int load(String path, int priority)
        //4.通过FileDescriptor加载
        //int load(FileDescriptor fd, long offset, long length, int priority)
        //声音ID 加载音频资源,这里用的是第二种，第三个参数为priority，声音的优先级*API中指出，priority参数目前没有效果，建议设置为1。
//                    final int voiceId = soundPool.load(this, , 1);
        AssetFileDescriptor descriptor = null;
        try {
            descriptor = getActivity().getResources().getAssets().openFd(soundFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        int voiceId = soundPool.load(descriptor, 1);
        //异步需要等待加载完成，音频才能播放成功
        soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                if (status == 0) {
                    //第一个参数soundID
                    //第二个参数leftVolume为左侧音量值（范围= 0.0到1.0）
                    //第三个参数rightVolume为右的音量值（范围= 0.0到1.0）
                    //第四个参数priority 为流的优先级，值越大优先级高，影响当同时播放数量超出了最大支持数时SoundPool对该流的处理
                    //第五个参数loop 为音频重复播放次数，0为值播放一次，-1为无限循环，其他值为播放loop+1次
                    //第六个参数 rate为播放的速率，范围0.5-2.0(0.5为一半速率，1.0为正常速率，2.0为两倍速率)
                    soundPool.play(voiceId, 1, 1, 1, 0, 1);
                }
            }
        });
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (!hidden) {
            initSettings();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        Log.e("tomato", "FragmentTomatoTime - onActivityResult");
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("tomato", "FragmentTomatoTime - onDestroy");
        activity.unbindService(conn);
        activity.unregisterReceiver(this.broadcastReceiver);
        handler.removeCallbacksAndMessages(null);
    }
}